package com.zhangtao.demo.common.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.*;

public class LotteryTurntableDataUtil {
    // 全量用户信息: 用户编号, 用户名称
    public static final Map<String, String> BASIC_USERCODE_USERNAME = new HashMap<>(200);


    public static String[] USERCODE = new String[]{"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", "020", "021", "022", "023", "024", "025", "026", "027", "028", "029", "030", "031", "032", "033", "034", "035", "036", "037", "038", "039", "040", "041", "042", "043", "044", "045", "046", "047", "048", "049", "050", "051", "052", "053", "054", "055", "056", "057", "058", "059", "060", "061", "062", "063", "064", "065", "066", "067", "068", "069", "070", "071", "072", "073", "074", "075", "076", "077", "078", "079", "080", "081", "082", "083", "084", "085", "086", "087", "088", "089", "090", "091", "092", "093", "094", "095", "096", "097", "098", "099", "0100", "0101", "0102", "0103", "0104", "0105", "0106", "0107", "0108", "0109", "0110", "0111", "0112", "0113", "0114", "0115", "0116", "0117", "0118", "0119", "0120", "0121", "0122", "0123", "0124", "0125", "0126", "0127", "0128", "0129", "0130", "0131", "0132", "0133", "0134", "0135", "0136", "0137", "0138", "0139", "0140", "0141", "0142", "0143", "0144", "0145", "0146", "0147", "0148", "0149", "0150", "0151", "0152", "0153", "0154", "0155", "0156", "0157", "0158", "0159", "0160", "0161", "0162", "0163", "0164", "0165", "0166", "0167", "0168", "0169", "0170", "0171", "0172", "0173", "0174", "0175", "0176", "0177", "0178", "0179", "0180", "0181", "0182", "0183", "0184", "0185", "0186", "0187", "0188", "0189", "0190", "0191", "0192", "0193", "0194", "0195", "0196", "0197", "0198", "0199"};

    public static void inputBasicInfo(Map<String, String> userInfo) {
        BASIC_USERCODE_USERNAME.clear();
        BASIC_USERCODE_USERNAME.putAll(userInfo);
        Set<Map.Entry<String, String>> es = userInfo.entrySet();
        Iterator<Map.Entry<String, String>> esi = es.iterator();
        List<String> userCode = new ArrayList<>(userInfo.size());
        while (esi.hasNext()) {
            Map.Entry<String, String> enty = esi.next();
            userCode.add(enty.getKey());
        }
        USERCODE = userCode.toArray(new String[userInfo.size()]);
        refreshLeveCount();
        System.out.println(JSONObject.toJSONString(BASIC_USERCODE_USERNAME));
        // 打乱USERCODE的顺序
        randomUserCode(USERCODE);
    }

    public static String currentLevelCode = "1";

    public static void setCurrentLevel(String level) {
        currentLevelCode = level;
    }

    public static final Map<String, String> LEVEL_NAME = new HashMap<>();

    static {
        LEVEL_NAME.put("0", "特等奖");
        LEVEL_NAME.put("1", "一等奖");
        LEVEL_NAME.put("2", "二等奖");
        LEVEL_NAME.put("3", "三等奖");
        LEVEL_NAME.put("4", "四等奖");
        LEVEL_NAME.put("5", "五等奖");
        LEVEL_NAME.put("6", "六等奖");
    }

    // 设置的每个奖项对应的总人数 中奖等级： 该奖项总人数
    public static final Map<String, Integer> LEVEL_COUNT = new HashMap<>(10);
    public static int totalLevelCount = 0;

    static {
        LEVEL_COUNT.put("0", 8);
        LEVEL_COUNT.put("1", 10);
        LEVEL_COUNT.put("2", 20);
        LEVEL_COUNT.put("3", 20);
        LEVEL_COUNT.put("4", 50);
        LEVEL_COUNT.put("5", 50);
        LEVEL_COUNT.put("6", 50);
    }

    // 设置的每次操作展示的中奖用户数量 中奖等级： 每次操作中奖用户
    public static final Map<String, Integer> PER_OPT_COUNT = new HashMap<>(10);

    static {
        PER_OPT_COUNT.put("0", 2);
        PER_OPT_COUNT.put("1", 5);
        PER_OPT_COUNT.put("2", 5);
        PER_OPT_COUNT.put("3", 5);
        PER_OPT_COUNT.put("4", 5);
        PER_OPT_COUNT.put("5", 16);
        PER_OPT_COUNT.put("6", 16);
    }

    /**
     * 设置奖项配置
     *
     * @param level    等级
     * @param name     显示的中文名称
     * @param count    奖项数量
     * @param optCount 每次操作中将人数
     */
    public static void setLevel(String level, String name, int count, int optCount) {
        if (StringUtils.isNotBlank(name)) {
            LEVEL_NAME.put(level, name);
        }
        if (count > 0) {
            LEVEL_COUNT.put(level, count);
        }
        if (optCount > 0) {
            PER_OPT_COUNT.put(level, optCount);
        }
        refreshLeveCount();
    }

    // -------------------------活动过程数据------------------------------------------------------
    // 存储已中奖的用户     用户编号 ： 中奖等级
    public static final Map<String, String> USERCODE_LEVEL = new HashMap<>(200);
    // 存储已中奖的用户记录    中奖等级 ： 已中奖数量
    public static final Map<String, Integer> LEVEL_USERCOUNT = new HashMap<>(200);

    public static void resetGame() {
        LEVEL_USERCOUNT.clear();
        USERCODE_LEVEL.clear();
    }

    public static void refreshLeveCount() {
        final BigDecimal[] total = {new BigDecimal(0)};
        LEVEL_COUNT.forEach((k, v) -> total[0] = total[0].add(new BigDecimal(v)));
        totalLevelCount = total[0].intValue();
    }

    private static boolean hasLevel(String userCode) {
        return USERCODE_LEVEL.containsKey(userCode);
    }

    /**
     * 设置指定奖项中奖总数
     *
     * @param level 中奖等级
     * @param count 总数
     */
    public static void setLevelCount(String level, int count) {
        LEVEL_COUNT.put(level, count);
        refreshLeveCount();
    }

    /**
     * 设置每次操作抽奖人数
     *
     * @param level 操作的奖项等级
     * @param count 每次抽中人数
     */
    public static void setPerOptLevelCount(String level, int count) {
        PER_OPT_COUNT.put(level, count);
    }

    /**
     * 点击抽奖按钮执行的方法
     *
     * @param level 抽取的奖项等级
     * @return 中奖用户编号列表
     */
    public static List<String> getUserCodeList(String level) {
        if (USERCODE_LEVEL.size() >= totalLevelCount) {
            // 抽奖结束,所有用户都中奖
            return null;
        }

        Integer alreadyCount = LEVEL_USERCOUNT.get(level);
        if (alreadyCount == null) {
            alreadyCount = 0;
        }
        Integer levelTotal = LEVEL_COUNT.get(level);
        int leftLevelCount = levelTotal - alreadyCount;
        if (leftLevelCount == 0) {
            return null;
        }
        Integer randomCount = PER_OPT_COUNT.get(level);
        if (leftLevelCount < randomCount) {
            randomCount = leftLevelCount;
        }
        List<String> userList = new ArrayList<>(randomCount);
        int fetchCount = 0;
        do {
            String userCode = generateAvalableUserCode();
            if (StringUtils.isNotBlank(userCode)) {
                fetchCount++;
                userList.add(userCode);
                // 存储中奖记录
                USERCODE_LEVEL.putIfAbsent(userCode, level);
                // 更新奖项中奖的人数
                Integer oldCount = LEVEL_USERCOUNT.get(level);
                if (oldCount == null) {
                    LEVEL_USERCOUNT.put(level, 1);
                } else {
                    LEVEL_USERCOUNT.put(level, ++oldCount);
                }
            }
        } while (fetchCount < randomCount);
        return userList;
    }

    private static String generateAvalableUserCode() {
        String userCode = "";
        do {
            int generate = RandomUtils.nextInt(0, USERCODE.length);
            if (generate < USERCODE.length) {
                userCode = USERCODE[generate];
            }
        } while (hasLevel(userCode) && USERCODE_LEVEL.size() < totalLevelCount);
        return userCode;
    }

    /**
     * 打乱用户数组
     *
     * @param oldUserCode 待打乱的数组
     */
    public static void randomUserCode(String[] oldUserCode) {
//        System.out.println(JSONObject.toJSONString(oldUserCode));
        LotteryTurntableDataUtil.USERCODE = ZTColllectionUtils.randomArray(oldUserCode, true);
        System.out.println(JSONObject.toJSONString(LotteryTurntableDataUtil.USERCODE));
    }

    public static void main(String[] args) {

        String[] oldarr = LotteryTurntableDataUtil.USERCODE;
        for (int i = 0; i < 100; i++) {
            ZTColllectionUtils.randomArray(oldarr, true);
        }

//        LotteryTurntableDataUtil.refreshLeveCount();
//        System.out.println("1=========================");
//        List<String> userlist;
//        do {
//            userlist = LotteryTurntableDataUtil.getUserCodeList("1");
//            System.out.println(JSONObject.toJSONString(userlist));
//        } while (userlist != null && !userlist.isEmpty());
//
//        System.out.println(JSONObject.toJSONString(LotteryTurntableDataUtil.USERCODE_LEVEL));
//        LotteryTurntableDataUtil.resetGame();
//        System.out.println("2=========================");
//        userlist = null;
//        do {
//            userlist = LotteryTurntableDataUtil.getUserCodeList("2");
//            System.out.println(JSONObject.toJSONString(userlist));
//        } while (userlist != null && !userlist.isEmpty());
//
//        System.out.println(JSONObject.toJSONString(LotteryTurntableDataUtil.USERCODE_LEVEL));

//        LotteryTurntableDataUtil.resetGame();
//        System.out.println("3=========================");
//        userlist = null;
//        do {
//            userlist = LotteryTurntableDataUtil.getUserCodeList("3");
//            System.out.println(JSONObject.toJSONString(userlist));
//        } while (userlist != null && !userlist.isEmpty());
//
//        System.out.println(JSONObject.toJSONString(LotteryTurntableDataUtil.USERCODE_LEVEL));


//        LotteryTurntableDataUtil.resetGame();
//        System.out.println("=========================");
//        System.out.println("=========================");
//        System.out.println("=========================");
//        System.out.println("=========================");
//        System.out.println("=========================");
//        userlist = null;
//        do {
//            userlist = LotteryTurntableDataUtil.getUserCodeList("1");
//            System.out.println(JSONObject.toJSONString(userlist));
//        } while (userlist != null && !userlist.isEmpty());
//
//        System.out.println(JSONObject.toJSONString(LotteryTurntableDataUtil.USERCODE_LEVEL));

//
//        LotteryTurntableDataUtil.resetGame();
//        System.out.println("2=========================");
//        userlist = null;
//        do {
//            userlist = LotteryTurntableDataUtil.getUserCodeList("2");
//            System.out.println(JSONObject.toJSONString(userlist));
//        } while (userlist != null && !userlist.isEmpty());
//
//        System.out.println(JSONObject.toJSONString(LotteryTurntableDataUtil.USERCODE_LEVEL));

    }
}
